﻿/*
 * common.cpp
 *
 *  Created on: 2020年5月3日
 *      Author: root
 */
//---------------------------------------------------------------------------

#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>

#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <error.h>
#include <net/route.h>

#include "common.h"
#include "log.h"
//---------------------------------------------------------------------------

bool IsExit = false;
//---------------------------------------------------------------------------

bool FileExists(char *pzfile)
{
	bool bRet = false;
	FILE *fp = fopen(pzfile, "r");
	if (fp) { fclose(fp); bRet = true; }
	return bRet;
}
//---------------------------------------------------------------------------

//去除首尾空白字符(<=0x20)
void Trim(char * &pzChar)
{
	while ((*pzChar != 0) && (*pzChar <= 0x20)) pzChar++;
	int x = strlen(pzChar) - 1;
	while ((x >= 0) && (pzChar[x] <= 0x20)) pzChar[x--] = 0;
}
//---------------------------------------------------------------------------

//同API inet_ntoa
void ntoipv4(uint32 n, char *pOut)
{
    BYTE b1, b2, b3, b4;
    b1 = ((n >> 24) & 0xFF);
    b2 = ((n >> 16) & 0xFF);
    b3 = ((n >> 8) & 0xFF);
    b4 = (n & 0xFF);
    sprintf(pOut, "%u.%u.%u.%u", b4, b3, b2, b1);
}
//---------------------------------------------------------------------------

//同API inet_addr
uint32 ipv4ton(const char *pzIp)
{
	char ch[4] = { 0 };
	BYTE v[4] = { 0 };
	int *pch = (int*)ch;
	int len = strlen(pzIp);
	int m = 0, n = 0;

	for(int i=0; i<len; i++)
	{
		if(pzIp[i] != '.') ch[m++] = pzIp[i];
		else
		{
			v[n++] = atoi(ch);
			m = 0;
			*pch = 0;
		}
	}

	v[n] = atoi(ch);
	return (v[0] | (v[1] << 8) | (v[2] << 16) | (v[3] << 24));
}
//---------------------------------------------------------------------------

//检查字符串IPv4合法性,xxx.xxx.xxx.xxx
//有效返回true,无效返回false
bool IsIPv4(const char *pzIp)
{
	bool bRet = false;
	char *p = (char*)pzIp;
	char ch[4] = { 0 };
	int *pch = (int*)ch;
	int m = 0, n = 0, v;

	for ( ; ; )
	{
		char & c = *p++;
		if ((c == '.') || (c == 0))
		{
			v = atoi(ch);
			n++;
			if ((v > 255) || (n > 4)) break;
			if (c == 0)
			{
				if(n == 4) bRet = true;
				break;
			}
			*pch = m = 0;
		}
		else
		{
			if(c < '0' || c > '9') break;
			ch[m++] = c;
			if(m > 3) break;
		}
	}

	return bRet;
}
//---------------------------------------------------------------------------

//计算CRC16(标准中石化算法)
uint16 CalcCRC16(BYTE *pBuff, int iSize)
{
	uint16 wCrc = 0;
	uint16 wPolynomial = 0xA001;
	for (int i = 0; i < iSize; i++)
	{
		wCrc ^= pBuff[i];
		for (int j = 0; j < 8; j++)
		{
			uint16 wInfo = wCrc & 0x0001;
			wCrc >>= 1;
			if (wInfo != 0) wCrc ^= wPolynomial;
		}
	}

	return wCrc;
}
//---------------------------------------------------------------------------

//0x00~0x0F -> '0'~'9' or 'A'~'F'
inline BYTE ByteToAsc(BYTE bt)
{
	return (bt < 10) ? (bt + '0') : (bt - 10 + 'A');
}
//---------------------------------------------------------------------------

//一字节转为两字节的ASCII表示
void ByteToAsc2(BYTE bt, BYTE asc[2])
{
	asc[0] = ByteToAsc(bt >> 4);
	asc[1] = ByteToAsc(bt & 0x0F);
}
//---------------------------------------------------------------------------

//'0'~'9' or 'A'~'F' -> 0x00~0x0F
BYTE AscToByte(BYTE bt)
{
	return (bt <= '9') ? (bt - '0') : (bt - 'A' + 10);
}
//---------------------------------------------------------------------------

//两字节16进制ASCII字符转为BYTE值: "00"~"FF" -> 0x00~0xFF
BYTE Asc2ToByte(BYTE asc[2])
{
    return (AscToByte(asc[0]) << 4) | AscToByte(asc[1]);
}
//---------------------------------------------------------------------------

//四字节16进制ASCII字符转为WORD值: "0000"~"FFFF" -> 0x0000~0xFFFF
uint16 Asc4ToWord(BYTE asc[4])
{
    return (Asc2ToByte(asc) << 8) | (Asc2ToByte(asc + 2));
}
//---------------------------------------------------------------------------

//八字节16进制ASCII字符转为UINT32值: "0000 0000"~"FFFF FFFF" -> 0x00000000~0xFFFFFFFF
uint32 Asc8ToUint32(BYTE asc[8])
{
    return (Asc4ToWord(asc) << 16) | (Asc4ToWord(asc + 4));
}
//---------------------------------------------------------------------------

//一字节16进制值(<=99)转一字节CBCD: 25 -> 0x25
BYTE ByteToCBCD(BYTE bt)
{
    bt %= 100;
    return ((bt / 10) << 4) | (bt % 10);
}
//---------------------------------------------------------------------------

//一字节CBCD码转一字节16进制值: 0x25 -> 25
BYTE CBCDToByte(BYTE bt)
{
    return ((bt >> 4) * 10) + (bt & 0x0F);
}
//---------------------------------------------------------------------------

//两字节值(<=9999)转成两字节CBCD 5678 -> 0x5678
uint16 WordToCBCD(uint16 w)
{
    BYTE bt[4] = {0};
    w %= 10000;
    for (int i = 3; i >= 0; i--)
    {
        bt[i] = w % 10;
        w /= 10;
    }

    return (((bt[0] << 4) | bt[1]) << 8) | ((bt[2] << 4) | bt[3]);
}
//-------------------------------------------------------------------------

//两字节压缩BCD转WORD值 0x0000~0x9999 -> 0~9999
uint16_t CBCDToWord(uint16_t w)
{
    BYTE bt[4] = {0};
    for (int i = 3; i >= 0; i--)
    {
        bt[i] = (w & 0x0F);
        w = (w >> 4);
    }

    return bt[0] * 1000 + bt[1] * 100 + bt[2] * 10 + bt[3];
}
//-------------------------------------------------------------------------

//取得当前日期时间
TTIMEX GetDateTime()
{
	TTIMEX dtime;
	timeval tv;
	gettimeofday(&tv, NULL);
	struct tm t;
	localtime_r(&tv.tv_sec, &t);

	dtime.Year = t.tm_year + 1900;
	dtime.Month = t.tm_mon + 1;
	dtime.Day = t.tm_mday;
	dtime.Hour = t.tm_hour;
	dtime.Min = t.tm_min;
	dtime.Sec = t.tm_sec;
	dtime.USec = tv.tv_usec;
	return dtime;
}
//---------------------------------------------------------------------------

//让调用线程休眠一段时间
void SleepEx(int ms, bool *pWorking)
{
	while (!IsExit && (ms > 0))
	{
		if (pWorking)
		{
			bool &Working = *pWorking;
			if (!Working) break;
		}

		int m = (ms > 10) ? 10 : ms;
		ms -= m;
		usleep(m * 1000);
	}
}
//---------------------------------------------------------------------------

//解码一帧数据(ASCII frame -> BIN frame),用于处理接收的帧数据
bool DecodeFrame(TFRAMEBIN *pfrm, BYTE *pBuffer, int iSize)
{
	TFRAMEBIN &frm = *pfrm;
	frm.Init();
	BYTE *p = pBuffer;
	BYTE *q = frm.Data;
	int i = 0;

	frm.HDR = p[i++];
	frm.Cmd = Asc2ToByte(p + i);
	i += 2;
	frm.DataSize = Asc2ToByte(p + i);			// 长度低字节先接收
	i += 2;
	frm.DataSize |= (Asc2ToByte(p + i) << 8);	// 长度高字节后接收
	i += 2;

	iSize -= 5;
	while (i < iSize)
	{
		*q++ = Asc2ToByte(p + i);
		i += 2;
	}

	frm.CRC = Asc2ToByte(p + i);					// 校验低字节先接收
	i += 2;
	frm.CRC |= Asc2ToByte(p + i) << 8;			// 校验高字节后接收
	i += 2;
	frm.TAIL = p[i];

	if (0 > frm.DataSize || MAXBINSIZE < frm.DataSize) return false;
	uint16 crc = CalcCRC16(&frm.Cmd, (int)(frm.DataSize + 3));
	return (crc == frm.CRC) ? true : false;
}
//---------------------------------------------------------------------------

//编码一帧数据(BIN frame -> ASCII frame)，用于处理要发送的帧数据
bool EncodeFrame(TFRAMEBIN *pfrm, BYTE *pBuffer, int &iSize)
{
	TFRAMEBIN &frm = *pfrm;
	BYTE *p = pBuffer;
	BYTE *q = frm.Data;
	if ((int)(frm.DataSize + 6) * 2 > iSize) return false;

	int i = 0;
	p[i++] = frm.HDR;
	ByteToAsc2(frm.Cmd, p + i);
	i += 2;
	ByteToAsc2((frm.DataSize & 0xFF), p + i);		// 长度低字节先发
	i += 2;
	ByteToAsc2((frm.DataSize >> 8), p + i);			// 长度高字节后发
	i += 2;

	for (uint16 j = 0; j < frm.DataSize; j++)
	{
		ByteToAsc2(q[j], p + i);
		i += 2;
	}

	ByteToAsc2((frm.CRC & 0xFF), p + i);			// 校验低字节先发送
	i += 2;
	ByteToAsc2((frm.CRC >> 8), p + i);				// 校验高字节后发送
	i += 2;
	p[i++] = frm.TAIL;
	iSize = i;
	return true;
}
//---------------------------------------------------------------------------

//计算一帧数据的CRC
void CalcFrameCRC(TFRAMEBIN *pfrm)
{
    TFRAMEBIN &frm = *pfrm;
    frm.CRC = CalcCRC16(&frm.Cmd, frm.DataSize + sizeof(BYTE) + sizeof(uint16));
}
//---------------------------------------------------------------------------

//自动化锁类
TLock::TLock()
{
	FInit = (pthread_mutex_init(&mutex, NULL) == 0) ? true : false;
}
//---------------------------------------------------------------------------

TLock::~TLock()
{
	if (FInit)
	{
		pthread_mutex_destroy(&mutex);
		FInit = false;
	}
}
//---------------------------------------------------------------------------

//指示锁是否初始化成功
bool TLock::GetInit()
{
	return FInit;
}
//---------------------------------------------------------------------------

//加锁
void TLock::Lock()
{
	if (FInit) pthread_mutex_lock(&mutex);
}
//---------------------------------------------------------------------------

//解锁
void TLock::Unlock()
{
	if (FInit) pthread_mutex_unlock(&mutex);
}
//---------------------------------------------------------------------------

//自动化内存类
TAutoMem::TAutoMem(uint32 uSize) : dwSize(0)
{
	pData = new BYTE[uSize];
	if (pData)
	{
		dwSize = uSize;
		memset(pData, 0, dwSize);
	}
}
//---------------------------------------------------------------------------

TAutoMem::~TAutoMem()
{
	Free();
}
//---------------------------------------------------------------------------

//重置大小
void TAutoMem::ReSize(uint32 uSize)
{
	if ((uSize != dwSize) && (uSize > 0))
	{
		Free();
		pData = new BYTE[uSize];
		if (pData)
		{
			dwSize = uSize;
			memset(pData, 0, dwSize);
		}
	}
}
//---------------------------------------------------------------------------

//释放空间
void TAutoMem::Free()
{
	if (pData)
	{
		delete []pData;
		pData = NULL;
		dwSize = 0;
	}
}
//---------------------------------------------------------------------------

//零填充
void TAutoMem::ZeroFill()
{
	if (pData) memset(pData, 0, dwSize);
}
//---------------------------------------------------------------------------

TTimerEx::TTimerEx()
{
	FTime0 = Now();
}
//---------------------------------------------------------------------------

//L_TIME to Seconds
UINT32 TTimerEx::L_TIME2Seconds(L_TIME ATime)
{
	return ATime.tv_sec;
}
//---------------------------------------------------------------------------

//L_TIME to Seconds Milliseconds
UINT32 TTimerEx::L_TIME2Milliseconds(L_TIME ATime)
{
	return UINT32(ATime.tv_sec * 1000 + ATime.tv_usec / 1000);
}
//---------------------------------------------------------------------------

//取当前时间值
L_TIME TTimerEx::Now()
{
	L_TIME tv;
	gettimeofday(&tv, NULL);
	return tv;
}
//---------------------------------------------------------------------------

//取当前时间值(秒数)
UINT32 TTimerEx::NowSeconds()
{
	L_TIME tv;
	gettimeofday(&tv, NULL);
	return L_TIME2Seconds(tv);
}
//---------------------------------------------------------------------------

//取当前时间值(毫秒数)
UINT32 TTimerEx::NowMilliseconds()
{
	L_TIME tv;
	gettimeofday(&tv, NULL);
	return L_TIME2Milliseconds(tv);
}
//---------------------------------------------------------------------------

//开始计时
void TTimerEx::Begin()
{
	FTime0 = Now();
}
//---------------------------------------------------------------------------

//从开始计时到现在经过的时间(毫秒数)
UINT32 TTimerEx::Elapsed()
{
	L_TIME tv;
	gettimeofday(&tv, NULL);
	return UINT32(L_TIME2Milliseconds(tv) - L_TIME2Milliseconds(FTime0));
}
//---------------------------------------------------------------------------


